package com.ruoyi.system.utils;


import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.UUID;
import java.util.regex.Pattern;

/**
 * Minio工具类
 *
 */
@Component
public class MinioUtils {

  // 自定义上传路径正则表达式
  private static final String PATH_REGEX = "^[a-zA-Z0-9_-]+(?:/[a-zA-Z0-9_-]+)*/$";

  // 编译正则表达式为Pattern
  private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX);

  @Autowired
  private MinioClient minioClient;

  /**
   * 桶名称
   */
  @Value("${minio.bucketName}")
  private String bucketName;

  /**
   * Minio文件上传接口
   *
   * @param file       上传的文件
   * @param customPath 自定义路径(格式：xxx/xx/.../)
   * @return 访问地址
   * @throws Exception 异常
   */
  public String uploadFile(MultipartFile file, String customPath) throws Exception {
    //文件名
    String originalFilename = file.getOriginalFilename();
    //文件流
    InputStream inputStream = file.getInputStream();
    //文件大小
    long size = file.getSize();
    //文件路径
    String filePath = createFilePath(originalFilename);
    if (!StringUtils.isEmpty(customPath)) {
      if (!PATH_PATTERN.matcher(customPath).matches()) {
        throw new Exception("自定义上传路径格式不正确，正确格式：xxx/xx/");
      }
      filePath = customPath + filePath;
    }
    //存储方法 putObject
    minioClient.putObject(PutObjectArgs.builder()
            .bucket(bucketName)
            .object(filePath)
            .stream(inputStream, size, -1)
            .contentType(file.getContentType())
            .build());
    IOUtils.closeQuietly(inputStream);
    return filePath;
  }

  /**
   * 获取文件路径
   *
   * @param originalFilename 原始文件名称
   * @return FilePath
   */
  public String createFilePath(String originalFilename) {
    UUID uuid = UUID.randomUUID();
    // 文件名前面加入UUID 防止服务器头像重复导致误删重复
    return uuid + "_" + originalFilename;
  }


  /**
   * 删除文件
   *
   * @param fileName 文件名(含路径)
   * @throws Exception 异常
   */
  public void deleteFile(String fileName) throws Exception {
    minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
  }


  /**
   * 下载文件
   *
   * @param filePath 文件路径
   */
  public void getObject(HttpServletResponse httpServletResponse, String filePath) throws Exception {
    String fileName = getFileName(filePath);
    InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
            .bucket(bucketName)
            .object(filePath)
            .build());
    downloadFile(httpServletResponse, inputStream, fileName);
  }

  /**
   * 根据文件路径获取文件名称
   *
   * @param filePath 文件路径
   * @return 文件名
   */
  public String getFileName(String filePath) {
    String[] split = StringUtils.split(filePath, "/");
    return split[split.length - 1];
  }

  /**
   * 下载文件
   *
   * @param httpServletResponse httpServletResponse
   * @param inputStream         inputStream
   * @param fileName            文件名
   * @throws IOException IOException
   */
  public void downloadFile(HttpServletResponse httpServletResponse, InputStream inputStream, String fileName) throws IOException {
    //设置响应头信息，告诉前端浏览器下载文件
    httpServletResponse.setContentType("application/octet-stream;charset=UTF-8");
    httpServletResponse.setCharacterEncoding("UTF-8");
    httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
    //获取输出流进行写入数据
    OutputStream outputStream = httpServletResponse.getOutputStream();
    // 将输入流复制到输出流
    byte[] buffer = new byte[4096];
    int bytesRead = -1;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
      outputStream.write(buffer, 0, bytesRead);
    }
    // 关闭流资源
    inputStream.close();
    outputStream.close();
  }

}
